package com.vimi8.app.framework.net

import com.alibaba.sdk.android.man.MANServiceProvider
import com.alibaba.sdk.android.man.network.MANNetworkErrorCodeBuilder
import com.alibaba.sdk.android.man.network.MANNetworkErrorInfo
import com.alibaba.sdk.android.man.network.MANNetworkPerformanceHitBuilder
import com.google.gson.GsonBuilder
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
import com.google.gson.TypeAdapter
import com.google.gson.Gson
import com.google.gson.TypeAdapterFactory
import com.google.gson.reflect.TypeToken
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonToken
import com.google.gson.stream.JsonWriter
import io.oschina.binv.kapp.framework.BaseApplication
import okhttp3.Interceptor
import okhttp3.Response
import java.io.IOException
import java.io.InterruptedIOException
import java.net.MalformedURLException
import java.net.SocketTimeoutException
import java.net.UnknownHostException
import kotlin.properties.Delegates


/**
 * Created by xuybin on 2017/7/25.
 */
object RetrofitFactory {

    private val networkPerformanceInterceptor= Interceptor { chain ->
        val builder = chain.request().newBuilder()
//        if (GlobalVariables.getInstance().accessToken.isNotEmpty()) {
//            builder.addHeader("Authorization", "bearer ${GlobalVariables.getInstance().accessToken}")
//        }
        val request = builder.build()


        //网络性能统计-打点
        val networkPerfBuilder = MANNetworkPerformanceHitBuilder("${request.url().host()}:${request.url().port()}", request.method().toUpperCase())
        networkPerfBuilder.hitRequestStart()
        networkPerfBuilder.withExtraInfo("RequestUrl", request.url().toString());


        var errorInfo : MANNetworkErrorInfo by Delegates.notNull()
        var originalResponse: Response by Delegates.notNull()
         try {
            originalResponse = chain.proceed(request)
             when{
                 originalResponse.isSuccessful->networkPerfBuilder.hitRequestEndWithLoadBytes(originalResponse.body()?.contentLength()?:0)
                 else->{
                     when{
                         originalResponse.code() >= 400 && originalResponse.code() < 500->errorInfo = MANNetworkErrorCodeBuilder.buildHttpCodeClientError4XX().withExtraInfo("ResponseCode",originalResponse.code().toString())
                         originalResponse.code() >= 500->errorInfo = MANNetworkErrorCodeBuilder.buildHttpCodeServerError5XX().withExtraInfo("ResponseCode", originalResponse.code().toString())
                     }
                     networkPerfBuilder.hitRequestEndWithError(errorInfo)
                     //此处不处理,留给上层处理 throw HttpError.newInstance(originalResponse.code(),originalResponse.request(),originalResponse.body())//必须抛出
                 }
             }
        }catch (ex: IOException) {
             when(ex){
                 is UnknownHostException->errorInfo = MANNetworkErrorCodeBuilder.buildIOException().withExtraInfo("ErrorEx", ex.message)
                 is MalformedURLException ->errorInfo = MANNetworkErrorCodeBuilder.buildMalformedURLException().withExtraInfo("ErrorEx", ex.message)
                 is InterruptedIOException ->errorInfo = MANNetworkErrorCodeBuilder.buildInterruptedIOException().withExtraInfo("ErrorEx", ex.message)
                 is SocketTimeoutException ->errorInfo = MANNetworkErrorCodeBuilder.buildSocketTimeoutException().withExtraInfo("ErrorEx", ex.message)
                 else-> errorInfo = MANNetworkErrorCodeBuilder.buildIOException().withExtraInfo("ErrorEx", ex.message)
             }
             networkPerfBuilder.hitRequestEndWithError(errorInfo)
             throw HttpError.newInstance(ex)//必须抛出
        }
        finally {
            //性能统计
            try {
                MANServiceProvider.getService().getMANAnalytics().getDefaultTracker().send(networkPerfBuilder.build());
            } catch (ex: Exception) {
            }
        }
        originalResponse
    }

    private val httpClient = OkHttpClient.Builder()
            // 添加通用的Header
            .addInterceptor(networkPerformanceInterceptor)
            .connectTimeout(30, TimeUnit.SECONDS)
            .readTimeout(30 * 2, TimeUnit.SECONDS)
            .build()

    private val gson = GsonBuilder()
            .registerTypeAdapterFactory(object : TypeAdapterFactory {
                override fun <T> create(gson: Gson, typeToken: TypeToken<T>): TypeAdapter<T>? {
                    val rawType = typeToken.getType() as Class<T>
//                    var isHaveNoParameterConstruction=false
//                    val constructors=rawType.getConstructors();
//                    for (constructor in constructors){
//                        if(!constructor.isVarArgs && constructor.parameterTypes!=null && constructor.parameterTypes.size==0){
//                            isHaveNoParameterConstruction=true;
//                            break
//                        }
//                    }
//                    if(!isHaveNoParameterConstruction){
//                        throw Exception("${rawType.canonicalName}需添加无参构造方法")
//                    }
                    if (rawType == String::class.java) {
                        //return StringNullAdapter() as TypeAdapter<T>
                        return object : TypeAdapter<String>() {
                            @Throws(IOException::class)
                            override fun read(reader: JsonReader): String {
                                // TODO Auto-generated method stub
                                if (reader.peek() === JsonToken.NULL) {
                                    reader.nextNull()
                                    return ""
                                }
                                return reader.nextString()
                            }

                            @Throws(IOException::class)
                            override fun write(writer: JsonWriter, value: String?) {
                                // TODO Auto-generated method stub
                                if (value == null) {
                                    writer.nullValue()
                                    return
                                }
                                writer.value(value)
                            }
                        } as TypeAdapter<T>
                    }
                    return null
                }
            })
            //配置你的Gson
            //.serializeNulls()
            //.setFieldNamingPolicy(FieldNamingPolicy.IDENTITY)
            //.setDateFormat("yyyy-MM-dd hh:mm:ss")
            // 此处可以添加Gson 自定义TypeAdapter
            //.registerTypeAdapter(UserInfo.class, new UserInfoTypeAdapter())
            .create()
    
    val instance = Retrofit.Builder()
            .baseUrl(BaseApplication.baseUrl)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .client(httpClient)
            .build()
}

